#include "fingerprint.h"
#include "freertos/idf_additions.h"
#include <driver/gpio.h>
#include <driver/uart.h>
#include <stdint.h>
#include <stdio.h>

#define BUF_SIZE 1024
#define UART_TX_PIN 21
#define UART_RX_PIN 20

void Fingerprint_Init(void) {
  uart_config_t config = {};
  config.baud_rate = 115200;
  config.data_bits = UART_DATA_8_BITS;
  config.stop_bits = UART_STOP_BITS_1;
  config.parity = UART_PARITY_DISABLE;
  config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
  config.source_clk = UART_SCLK_DEFAULT;

  uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);
  uart_param_config(UART_NUM_1, &config);
  // 为串口1分配tx和rx引脚
  uart_set_pin(UART_NUM_1, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE,
               UART_PIN_NO_CHANGE);

  // 初始化中断引脚
  gpio_config_t io_config = {};
  io_config.intr_type = GPIO_INTR_POSEDGE;
  io_config.mode = GPIO_MODE_INPUT;
  io_config.pin_bit_mask = (1ULL << FINGERPRINT_TOUCH_INT);
  gpio_config(&io_config);

  vTaskDelay(200/portTICK_PERIOD_MS);
}

void Fingerprint_GetSerialNumber(void) {
  uint8_t recv_data[128] = {0};

  // 获取芯片唯一序列号 0x34。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[13] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x04,             // 包长度
      0x34,                   // 指令码
      0x00,                   // 参数
      0x00, 0x39              // 校验和sum
  };
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 13);

  // Read data from the UART
  int len = uart_read_bytes(UART_NUM_1, recv_data, (BUF_SIZE - 1),
                            100 / portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("指纹模块序列号: %.32s\r\n", &recv_data[10]);
    } else if (recv_data[6] == 0x07 && recv_data[9] == 0x01) {
      printf("获取指纹序列号收包错误。\r\n");
    }
  }
}

uint8_t Fingerprint_GetTemplatesCount(void) {
  uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[12] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x03,             // 包长度
      0x1d,                   // 指令码
      0x00, 0x21              // 校验和sum
  };
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 12);

  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 100/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("指纹库中模板数量: %d\r\n", recv_data[11]); // 模板数量

      return recv_data[11];
   }else {
    printf("获取指纹库中模板数量收包错误。\r\n");
    return 0xff;
   }
  }
  else {
    printf("获取指纹库中模板数量失败。\r\n");
    return 0xff;
  }
}

void Fingerprint_Sleep(void) {
  uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[12] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x03,             // 包长度
      0x33,                   // 指令码
      0x00, 0x37              // 校验和sum
  };
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 12);

  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 100/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("进入休眠模式\r\n"); // 模板数量
   } else{
    printf("休眠失败\r\n");
   }
  }
}

void Fingerprint_Cancel(void){
   uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[12] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x03,             // 包长度
      0x30,                   // 指令码
      0x00, 0x34              // 校验和sum
  };
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 12);

  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 100/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("取消指令执行成功\r\n"); // 模板数量
   } else{
    printf("取消指令执行成功\r\n");
   }
  }
}

uint8_t Fingerprint_GetImage(void) {
  uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[12] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x03,             // 包长度
      0x01,                   // 指令码
      0x00, 0x5             // 校验和sum
  };
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 12);

  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 150/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) 
    {
      printf("获取指纹成功\r\n");
      return 0; // 获取指纹图像成功
    } 
    else if(recv_data[6] == 0x07 && recv_data[9] == 0x01){
      printf("获取指纹失败，请重试\r\n");
      return 1; // 获取指纹图像失败，请重试
   }else{
      printf("指纹传感器上无指纹\r\n");
      return 1; // 获取指纹图像失败
   }
  }else {
    return 1; // 获取指纹图像失败
  }
}

uint8_t Fringerprint_GenChar(uint8_t BufferId)
{
  uint8_t recv_data[128] = {0};

  // 生成特征 0x02。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[13] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x04,             // 包长度
      0x02,                   // 指令码
      BufferId,               // 参数 
      0x00, 0x5             // 校验和sum
  };

  uint16_t sum = cmd[6] + cmd[7] + cmd[8] + cmd[9] + cmd[10];
  cmd[11] = sum >> 8;
  cmd[12] = sum & 0xff;
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 13);

  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 150/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) 
    {
      printf("生成指纹特征成功\r\n");
      return 0; // 获取指纹图像成功
    } 
    else if(recv_data[6] == 0x07 && recv_data[9] == 0x01){
      printf("生成指纹特征收包错误，请重试\r\n");
      return 2; // 获取指纹图像失败，请重试
    }
    else if(recv_data[6] == 0x07 && recv_data[9] == 0x06){
      printf("指纹图像太乱，请重试\r\n");
      return 2; // 获取指纹图像失败，请重试
    }
    else if(recv_data[6] == 0x07 && recv_data[9] == 0x07){
      printf("指纹特征太少，请重试\r\n");
      return 2; // 获取指纹图像失败，请重试
    }
    else if(recv_data[6] == 0x07 && recv_data[9] == 0x08){
      printf("指纹与上一个指纹无关联\r\n");
      return 2; // 获取指纹图像失败，请重试
    }
    else if(recv_data[6] == 0x07 && recv_data[9] == 0x0A){
      printf("合并指纹特征失败\r\n");
      return 2; // 获取指纹图像失败，请重试
    }
    else{
      return 1; // 获取指纹图像失败
    }
  }else {
    return 1; // 获取指纹图像失败
  }
  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
}

uint8_t Fringerprint_RegisterTemplate(void)
{
   uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[12] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x03,             // 包长度
      0x05,                   // 指令码
      0x00, 0x09             // 校验和sum
  };
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 12);

  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 500/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("mode合并成功\r\n"); // 模板数量
      return 0;
    } else{
      printf("mode合并失败\r\n");
      return 1;
    }
  } 
  else {
    return 1;
  }
}

uint8_t Fingerprint_StoreTemplate(uint16_t PageID)
{
   uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[15] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x06,             // 包长度
      0x06,                   // 指令码
      0x01,                   // 缓冲区号默认为0x01
      0x00, 0x00,             // 指纹库位置号
      0x00, 0x09             // 校验和sum
  };
  cmd[11] = PageID >> 8;
  cmd[12] = PageID & 0xff;
  uint16_t sum = cmd[6] + cmd[7] + cmd[8] + cmd[9] + cmd[10] + cmd[11] + cmd[12];
  cmd[13] = sum >> 8;
  cmd[14] = sum & 0xff;
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 15);
  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 500/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("指纹模板存储成功\r\n"); // 模板数量
      return 0;
    } else if (recv_data[6] == 0x07 && recv_data[9] == 0x0B) {
      printf("PageID超出指纹库范围\r\n"); // 模板数量
      return 1;
    }
    else if (recv_data[6] == 0x07 && recv_data[9] == 0x18) {
      printf("写入指纹模块flash失败\r\n"); // 模板数量
      return 1;
    }
    else{
      printf("mode合并失败\r\n");
      return 1;
    }
  } else {
    return 1;
  }
}

uint8_t Fingerprint_SetSecurityLevel(uint8_t level)
{
   uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[14] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x05,             // 包长度
      0x0E,                   // 指令码
      0x07,                   // 缓冲区号默认为0x01
      level,                   // 加密等级
      0x00, 0x09             // 校验和sum
  };
  uint16_t sum = cmd[6] + cmd[7] + cmd[8] + cmd[9] + cmd[10] + cmd[11];
  cmd[12] = sum >> 8;
  cmd[13] = sum & 0xff;
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 14);

  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 100/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("设置成功\r\n"); // 模板数量
      return 0;
    }
    else{
      printf("设置失败\r\n");
      return 1;
    }
  } else {
    return 1;
  }
}

uint8_t Fingerprint_Enroll(uint16_t PageId)
{
  uint8_t n = 1;
sendGetImageLabel:
  if (Fingerprint_GetImage()) {
    goto sendGetImageLabel;
  }
  printf("第%d次获取指纹图像成功\r\n", n);
  // todo 播放音乐提示用户放置手指
  if (Fringerprint_GenChar(n)) {
    goto sendGetImageLabel;
  }
  printf("第%d次生成指纹特征成功\r\n", n);
  n++;
  vTaskDelay(2000 / portTICK_PERIOD_MS);
  if(n < 8){
    goto sendGetImageLabel;
  }
  if (Fringerprint_RegisterTemplate()) {
    goto ERROR;
  }
  if( Fingerprint_StoreTemplate(PageId)){
    goto ERROR;
  }
  printf("指纹添加成功\r\n");
  return 0;
ERROR:
  return 1;
}


static uint8_t Fringerprint_Search()
{
   uint8_t recv_data[128] = {0};

  // 获取指纹库中模板数量 0x1d。确认码=00H 表示 OK；确认码=01H 表示收包有错。
  uint8_t cmd[17] = {
      0xEF, 0x01,             // 包头
      0xFF, 0xFF, 0xFF, 0xFF, // 默认的设备地址
      0x01,                   // 包标识
      0x00, 0x08,             // 包长度
      0x04,                   // 指令码
      0x01,                   // 缓冲区号默认为0x01
      0x00, 0x00,             // startPage
      0xFF, 0xFF,             // PageNum
      0x02, 0x0C             // 校验和sum
  };
  uart_write_bytes(UART_NUM_1, (const char *)cmd, 17);
  // Read data from the UART.
  int len = uart_read_bytes(UART_NUM_1, recv_data,BUF_SIZE - 1, 400/portTICK_PERIOD_MS);

  if (len > 0) {
    if (recv_data[6] == 0x07 && recv_data[9] == 0x00) {
      printf("搜索指纹成功\r\n"); // 模板数量
      return 0;
    }
    else{
      printf("搜索失败\r\n");
      return 1;
    }
  } else {
    return 1;
  }
}

uint8_t Fingerprint_Identify(void)
{
  if( Fingerprint_GetImage()){
    return 1;
  }
  if(Fringerprint_GenChar (1)){
    return 1;
  }
  if(Fringerprint_Search()){
    return 1;
  }
  return 0;
}


